/*
-----------------------------------------------------------------------------
This source file is part of Labor3D
(Labor 3D Graphics Engine)

Copyright (c) 2009-2020 Rock Mao
* creator : Rock Mao
* created : 2009-5-4   16:45
* filename: LaborCore.cpp

-----------------------------------------------------------------------------
*/
#include "LaborCore.h"
#include "../include/Plugin/LaborDynLibMgr.h"
#include "../include/Renderer/LaborRenderSystem.h"
NAMESPACE_LABOR3D_BEGIN

//-----------------------------------------------------------------------
template<> CLCore* CLSingleton<CLCore>::ms_Singleton = 0;

typedef void (*DLL_START_PLUGIN)(void);
typedef void (*DLL_STOP_PLUGIN)(void);

//---------------------------------------------------------------------
CLCore::CLCore()
: mIsInitialised(false)
, m_pCurrentRenderer(NULL)
{

}

//---------------------------------------------------------------------
CLCore::~CLCore()
{
	destory();
	unloadPlugins();
}

//---------------------------------------------------------------------
void CLCore::initialise()
{
	mIsInitialised = true;
}

//---------------------------------------------------------------------
void CLCore::destory(void)
{
	mIsInitialised = false;
}


//---------------------------------------------------------------------
void CLCore::addRenderSystem( CLRenderSystem* pNewRenderer )
{
	m_Renderers.push_back(pNewRenderer);

}

//---------------------------------------------------------------------
void CLCore::setRenderSystem( CLRenderSystem* pRenderer )
{
	if( m_pCurrentRenderer && m_pCurrentRenderer != pRenderer )
	{
		m_pCurrentRenderer->destroy();
	}

	m_pCurrentRenderer = pRenderer;
}

//---------------------------------------------------------------------
CLRenderSystem* CLCore::getRenderSystem() 
{
	assert( m_pCurrentRenderer );
	return m_pCurrentRenderer; 
}

//-----------------------------------------------------------------------
RenderSystemList* CLCore::getAvailableRenderers(void)
{
	// Returns a vector of renders

	return &m_Renderers;

}

//-----------------------------------------------------------------------
CLRenderSystem* CLCore::getRenderSystemByName(const CLString& name)
{
	if (name.empty())
	{
		// No render system
		return NULL;
	}

	RenderSystemList::const_iterator pRend;
	for (pRend = getAvailableRenderers()->begin(); pRend != getAvailableRenderers()->end(); ++pRend)
	{
		CLRenderSystem* rs = *pRend;
		if (rs->getName() == name)
			return rs;
	}

	// Unrecognised render system
	return NULL;
}

//---------------------------------------------------------------------
void CLCore::installPlugin(CLPlugin* plugin)
{
	if ( NULL == plugin )
	{
		printf("The plugin pointer is NULL \n", plugin->getName());
		return;
	}

	m_Plugins.push_back(plugin);
	plugin->install();

	// if rendersystem is already initialised, call rendersystem init too
	if (mIsInitialised)
	{
		plugin->initialise();
	}
	//XGUI_LOG(1,"Find a plugin file = %s \n"  , pluginFile);
	printf("              name = %s \n", plugin->info().m_Name);
	printf("              ID   = 0X%X \n", plugin->info().m_ID);
	printf("              desc = %s \n", plugin->info().m_Description);


}

//---------------------------------------------------------------------
void CLCore::uninstallPlugin(CLPlugin* plugin)
{
	if ( NULL == plugin )
	{
		printf("The plugin pointer is NULL \n");
		return;
	}
	
	printf("Uninstalling plugin:%s\n", plugin->getName());
	PluginInstanceList::iterator i = 
		std::find(m_Plugins.begin(), m_Plugins.end(), plugin);
	if (i != m_Plugins.end())
	{
		if (mIsInitialised)
			plugin->destory();
		plugin->uninstall();
		m_Plugins.erase(i);
	}
	printf("Plugin successfully uninstalled:%s\n", plugin->getName());

}
//-----------------------------------------------------------------------
void CLCore::loadPlugin(const CLString& pluginName)
{
	if ( pluginName.empty() )
	{
		printf("The plugin name is NULL \n");
		return;
	}
	// Load plugin library
	CLDynLib* lib = GetDynLibMgr()->load( pluginName );
	// Store for later unload
	m_PluginLibs.push_back(lib);

	// Call startup function
	DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol(L"dllStartPlugin");

	if (!pFunc)
		wprintf(L"Cannot find symbol dllStartPlugin in library %s\n", pluginName);

	// This must call installPlugin
	pFunc();

}
//-----------------------------------------------------------------------
void CLCore::unloadPlugin(const CLString& pluginName)
{
	if ( pluginName.empty() )
	{
		printf("The plugin name is NULL \n");
		return;
	}
	PluginLibList::iterator i;

	for (i = m_PluginLibs.begin(); i != m_PluginLibs.end(); ++i)
	{
		if ((*i)->getName() == pluginName)
		{
			// Call plugin shutdown
			DLL_STOP_PLUGIN pFunc = (DLL_STOP_PLUGIN)(*i)->getSymbol(L"dllStopPlugin");
			// this must call uninstallPlugin
			pFunc();
			// Unload library (destroyed by DynLibManager)
			GetDynLibMgr()->unload(*i);
			m_PluginLibs.erase(i);
			return;
		}

	}
}

//-----------------------------------------------------------------------
void CLCore::loadPlugins( const CLString& pluginsfile )
{
	StringVector pluginList;
	CLString pluginDir;
//	ConfigFile cfg;
//
//	try {
//		cfg.load( pluginsfile );
//	}
//	catch (Exception)
//	{
//		LogManager::getSingleton().logMessage(pluginsfile + " not found, automatic plugin loading disabled.");
//		return;
//	}
//
//	pluginDir = cfg.getSetting("PluginFolder"); // Ignored on Mac OS X, uses Resources/ directory
//	pluginList = cfg.getMultiSetting("Plugin");
//
//#if OGRE_PLATFORM != OGRE_PLATFORM_APPLE
//	if (pluginDir.empty())
//	{
//		// User didn't specify plugins folder, try current one
//		pluginDir = ".";
//	}
//#endif
//
//	char last_char = pluginDir[pluginDir.length()-1];
//	if (last_char != '/' && last_char != '\\')
//	{
//#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
//		pluginDir += "\\";
//#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
//		pluginDir += "/";
//#endif
//	}
//
//	for( StringVector::iterator it = pluginList.begin(); it != pluginList.end(); ++it )
//	{
//		loadPlugin(pluginDir + (*it));
//	}

}
//-----------------------------------------------------------------------
void CLCore::destoryPlugins(void)
{
	// NB Shutdown plugins in reverse order to enforce dependencies
	for (PluginInstanceList::reverse_iterator i = m_Plugins.rbegin(); i != m_Plugins.rend(); ++i)
	{
		(*i)->destory();
	}
}
//-----------------------------------------------------------------------
void CLCore::initialisePlugins(void)
{
	for (PluginInstanceList::iterator i = m_Plugins.begin(); i != m_Plugins.end(); ++i)
	{
		(*i)->initialise();
	}
}
//-----------------------------------------------------------------------
void CLCore::unloadPlugins(void)
{
	// unload dynamic libs first
	for (PluginLibList::reverse_iterator i = m_PluginLibs.rbegin(); i != m_PluginLibs.rend(); ++i)
	{
		// Call plugin shutdown
		DLL_STOP_PLUGIN pFunc = (DLL_STOP_PLUGIN)(*i)->getSymbol(L"dllStopPlugin");
		// this will call uninstallPlugin
		pFunc();
		// Unload library & destroy
		GetDynLibMgr()->unload(*i);

	}
	m_PluginLibs.clear();

	// now deal with any remaining plugins that were registered through other means
	for (PluginInstanceList::reverse_iterator i = m_Plugins.rbegin(); i != m_Plugins.rend(); ++i)
	{
		// Note this does NOT call uninstallPlugin - this shutdown is for the 
		// detail objects
		(*i)->uninstall();
	}
	m_Plugins.clear();

}

NAMESPACE_LABOR3D_END

